<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>分布式存储虚拟机资源计算器</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 1100px;
            margin: 0 auto;
            padding: 25px;
            line-height: 1.6;
            color: #333;
            background-color: #f8f9fa;
        }
        h1 {
            color: #2c3e50;
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 15px;
            border-bottom: 1px solid #e1e4e8;
        }
        .calculator {
            background-color: white;
            border-radius: 10px;
            padding: 30px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.08);
            margin-bottom: 30px;
        }
        .form-group {
            margin-bottom: 20px;
        }
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #2c3e50;
        }
        input, select {
            width: 100%;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 6px;
            box-sizing: border-box;
            font-size: 15px;
            transition: border-color 0.3s;
        }
        input:focus, select:focus {
            border-color: #3498db;
            outline: none;
            box-shadow: 0 0 0 3px rgba(52,152,219,0.1);
        }
        button {
            background-color: #3498db;
            color: white;
            border: none;
            padding: 14px 20px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 16px;
            width: 100%;
            margin-top: 20px;
            transition: background-color 0.3s;
            font-weight: 600;
        }
        button:hover {
            background-color: #2980b9;
        }
        .result {
            margin-top: 30px;
            padding: 25px;
            background-color: #f8fafc;
            border-radius: 8px;
            display: none;
            border: 1px solid #e1e4e8;
        }
        .result h3 {
            margin-top: 0;
            color: #2c3e50;
            border-bottom: 1px solid #e1e4e8;
            padding-bottom: 12px;
            margin-bottom: 20px;
        }
        .result-section {
            margin-bottom: 20px;
            padding: 18px;
            background-color: white;
            border-radius: 6px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.05);
            border: 1px solid #e1e4e8;
        }
        .result-section h4 {
            margin-top: 0;
            color: #3498db;
            font-size: 1.1em;
        }
        .explanation {
            margin-top: 40px;
            font-size: 0.95em;
            color: #5a6268;
            background-color: #f8f9fa;
            padding: 20px;
            border-radius: 8px;
            border: 1px solid #e1e4e8;
        }
        .section {
            margin-bottom: 30px;
            padding-bottom: 20px;
            border-bottom: 1px solid #e1e4e8;
        }
        .section-title {
            font-size: 1.25em;
            color: #2c3e50;
            margin-bottom: 18px;
            font-weight: 600;
            display: flex;
            align-items: center;
        }
        .section-title:before {
            content: "";
            display: inline-block;
            width: 6px;
            height: 24px;
            background-color: #3498db;
            margin-right: 12px;
            border-radius: 3px;
        }
        .advanced-toggle {
            background-color: #e9ecef;
            padding: 12px 18px;
            border-radius: 6px;
            cursor: pointer;
            margin-bottom: 20px;
            user-select: none;
            font-weight: 600;
            display: flex;
            justify-content: space-between;
            align-items: center;
            transition: background-color 0.2s;
        }
        .advanced-toggle:hover {
            background-color: #dee2e6;
        }
        .advanced-settings {
            display: none;
            background-color: #f8f9fa;
            padding: 20px;
            border-radius: 6px;
            margin-bottom: 20px;
            animation: fadeIn 0.3s;
            border: 1px solid #e1e4e8;
        }
        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
        .resource-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
            gap: 18px;
            margin-top: 18px;
        }
        .resource-item {
            background-color: white;
            padding: 15px;
            border-radius: 6px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.05);
            border: 1px solid #e1e4e8;
        }
        .resource-item strong {
            color: #3498db;
            font-size: 1.05em;
        }
        small {
            color: #6c757d;
            font-size: 0.85em;
            display: block;
            margin-top: 5px;
            line-height: 1.4;
        }
        .highlight {
            color: #e74c3c;
            font-weight: 600;
        }
        .storage-details {
            margin-top: 15px;
            padding: 12px;
            background-color: #f1f8fe;
            border-radius: 4px;
            border-left: 4px solid #3498db;
        }
    </style>
</head>
<body>
    <h1>分布式存储虚拟机资源计算器</h1>
    
    <div class="calculator">
        <div class="section">
            <div class="section-title">基本虚拟机配置</div>
            <div class="form-group">
                <label for="vmCount">虚拟机数量:</label>
                <input type="number" id="vmCount" min="1" value="44">
            </div>
            
            <div class="form-group">
                <label for="cpuPerVM">每台虚拟机vCPU数量:</label>
                <input type="number" id="cpuPerVM" min="1" value="8">
            </div>
            
            <div class="form-group">
                <label for="ramPerVM">每台虚拟机内存(GB):</label>
                <input type="number" id="ramPerVM" min="1" step="0.1" value="16">
            </div>
            
            <div class="form-group">
                <label for="storagePerVM">每台虚拟机存储(GB):</label>
                <input type="number" id="storagePerVM" min="1" value="300">
            </div>
        </div>
        
        <div class="section">
            <div class="section-title">超配比设置</div>
            <div class="form-group">
                <label for="cpuOvercommit">CPU超配比 (n:1):</label>
                <input type="number" id="cpuOvercommit" min="1" step="0.1" value="2">
                <small>1.5表示1个物理核心可运行1.5个虚拟核心</small>
            </div>
            
            <div class="form-group">
                <label for="ramOvercommit">内存超配比 (n:1):</label>
                <input type="number" id="ramOvercommit" min="1" step="0.1" value="1">
                <small>1.2表示1GB物理内存可分配1.2GB虚拟内存</small>
            </div>
            
            <div class="form-group">
                <label for="storageOvercommit">存储超配比 (n:1):</label>
                <input type="number" id="storageOvercommit" min="1" step="0.1" value="1">
                <small>1.5表示1GB物理存储可分配1.5GB虚拟存储</small>
            </div>
        </div>
        
        <div class="advanced-toggle" onclick="toggleAdvancedSettings()">
            <span>高级设置（系统预留与分布式存储）</span>
            <span id="toggleIcon">▼</span>
        </div>
        
        <div id="advancedSettings" class="advanced-settings">
            <div class="section-title">系统预留资源</div>
            <div class="form-group">
                <label for="systemCpuReserve">系统预留CPU核心数:</label>
                <input type="number" id="systemCpuReserve" min="0" step="0.1" value="16">
                <small>为宿主机系统预留的CPU核心数</small>
            </div>
            
            <div class="form-group">
                <label for="systemRamReserve">系统预留内存(GB):</label>
                <input type="number" id="systemRamReserve" min="0" step="0.1" value="32">
                <small>为宿主机系统预留的内存</small>
            </div>
            
            <div class="form-group">
                <label for="systemStorageReserve">系统预留存储(GB):</label>
                <input type="number" id="systemStorageReserve" min="0" step="0.1" value="32">
                <small>为宿主机系统预留的存储空间</small>
            </div>
            
            <div class="section-title">资源缓冲设置</div>
            <div class="form-group">
                <label for="cpuBuffer">CPU缓冲百分比(%):</label>
                <input type="number" id="cpuBuffer" min="0" max="100" value="0">
                <small>额外预留的CPU资源百分比</small>
            </div>
            
            <div class="form-group">
                <label for="ramBuffer">内存缓冲百分比(%):</label>
                <input type="number" id="ramBuffer" min="0" max="100" value="0">
                <small>额外预留的内存资源百分比</small>
            </div>
            
            <div class="form-group">
                <label for="storageBuffer">存储缓冲百分比(%):</label>
                <input type="number" id="storageBuffer" min="0" max="100" value="0">
                <small>额外预留的存储资源百分比</small>
            </div>
            
            <div class="section-title">分布式存储配置</div>
            <div class="form-group">
                <label for="serverCount">服务器/宿主机数量:</label>
                <input type="number" id="serverCount" min="1" value="2">
                <small>用于计算每台服务器的平均资源分配</small>
            </div>
            
            <div class="form-group">
                <label for="replicaCount">存储副本数:</label>
                <input type="number" id="replicaCount" min="1" max="5" value="3">
                <small>分布式存储系统中数据的副本数量</small>
            </div>
            
            <div class="form-group">
                <label for="storageType">存储类型:</label>
                <select id="storageType">
                    <option value="replicated">复制式存储 (Replicated)</option>
                    <option value="erasure">纠删码存储 (Erasure Coding)</option>
                </select>
                <small>选择分布式存储的类型</small>
            </div>
            
            <div id="erasureConfig" style="display:none;">
                <div class="form-group">
                    <label for="dataChunks">数据块数量 (k):</label>
                    <input type="number" id="dataChunks" min="1" value="4">
                </div>
                
                <div class="form-group">
                    <label for="parityChunks">校验块数量 (m):</label>
                    <input type="number" id="parityChunks" min="1" value="2">
                </div>
            </div>
        </div>
        
        <button onclick="calculateResources()">计算资源需求</button>
        
        <div id="result" class="result">
            <h3>资源计算结果</h3>
            
            <div class="result-section">
                <h4>虚拟机总需求</h4>
                <div class="resource-grid">
                    <div class="resource-item">
                        <strong>vCPU总数:</strong> <span id="totalVCpu"></span>
                        <small>(虚拟机数量 × 每台vCPU)</small>
                    </div>
                    <div class="resource-item">
                        <strong>虚拟内存总数:</strong> <span id="totalVRam"></span> GB
                        <small>(虚拟机数量 × 每台内存)</small>
                    </div>
                    <div class="resource-item">
                        <strong>虚拟存储总数:</strong> <span id="totalVStorage"></span> GB
                        <small>(虚拟机数量 × 每台存储)</small>
                    </div>
                </div>
            </div>
            
            <div class="result-section">
                <h4>物理资源总需求</h4>
                <div class="resource-grid">
                    <div class="resource-item">
                        <strong>物理CPU核心需求:</strong> <span id="physicalCpu"></span>
                        <small>(总vCPU/超配比 + 系统预留)</small>
                    </div>
                    <div class="resource-item">
                        <strong>物理内存需求:</strong> <span id="physicalRam"></span> GB
                        <small>(总内存/超配比 + 系统预留)</small>
                    </div>
                    <div class="resource-item">
                        <strong>物理存储需求:</strong> <span id="physicalStorage"></span> GB
                        <small>(总存储/超配比 + 系统预留)</small>
                    </div>
                </div>
            </div>
            
            <div class="result-section">
                <h4>推荐总配置（含缓冲）</h4>
                <div class="resource-grid">
                    <div class="resource-item">
                        <strong>推荐CPU核心数:</strong> <span id="recommendedCpu"></span>
                        <small>(物理需求 + <span id="cpuBufferValue"></span>%)</small>
                    </div>
                    <div class="resource-item">
                        <strong>推荐内存容量:</strong> <span id="recommendedRam"></span> GB
                        <small>(物理需求 + <span id="ramBufferValue"></span>%)</small>
                    </div>
                    <div class="resource-item">
                        <strong>推荐存储容量:</strong> <span id="recommendedStorage"></span> GB
                        <small>(物理需求 + <span id="storageBufferValue"></span>%)</small>
                    </div>
                </div>
            </div>
            
            <div class="result-section">
                <h4>分布式存储需求</h4>
                <div class="storage-details">
                    <p><strong>存储类型:</strong> <span id="storageTypeValue"></span></p>
                    <p><strong>存储冗余系数:</strong> <span id="redundancyFactor"></span></p>
                    <p><strong>实际物理存储需求:</strong> <span id="actualPhysicalStorage"></span> GB</p>
                    <p><strong>考虑冗余后的总存储需求:</strong> <span id="totalStorageWithRedundancy"></span> GB</p>
                </div>
            </div>
            
            <div class="result-section">
                <h4>每台服务器平均分配</h4>
                <div class="resource-grid">
                    <div class="resource-item">
                        <strong>每台服务器CPU:</strong> <span id="perServerCpu"></span> 核心
                        <small>(推荐总CPU/服务器数量)</small>
                    </div>
                    <div class="resource-item">
                        <strong>每台服务器内存:</strong> <span id="perServerRam"></span> GB
                        <small>(推荐总内存/服务器数量)</small>
                    </div>
                    <div class="resource-item">
                        <strong>每台服务器存储:</strong> <span id="perServerStorage"></span> GB
                        <small>(考虑冗余后的总存储/服务器数量)</small>
                    </div>
                    <div class="resource-item">
                        <strong>每台服务器虚拟机数:</strong> <span id="perServerVm"></span>
                        <small>(总虚拟机数/服务器数量)</small>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <div class="explanation">
        <h3>计算说明:</h3>
        <p><strong>基本计算:</strong></p>
        <p>物理CPU核心需求 = (虚拟机数量 × 每台虚拟机vCPU) / CPU超配比 + 系统预留CPU</p>
        <p>物理内存需求 = (虚拟机数量 × 每台虚拟机内存) / 内存超配比 + 系统预留内存</p>
        <p>物理存储需求 = (虚拟机数量 × 每台虚拟机存储) / 存储超配比 + 系统预留存储</p>
        
        <p><strong>最终推荐配置:</strong></p>
        <p>推荐CPU = 物理CPU需求 × (1 + CPU缓冲百分比/100)</p>
        <p>推荐内存 = 物理内存需求 × (1 + 内存缓冲百分比/100)</p>
        <p>推荐存储 = 物理存储需求 × (1 + 存储缓冲百分比/100)</p>
        
        <p><strong>分布式存储计算:</strong></p>
        <p><span class="highlight">复制式存储:</span> 总存储需求 = 推荐存储 × 副本数</p>
        <p><span class="highlight">纠删码存储:</span> 总存储需求 = 推荐存储 × (数据块数 + 校验块数) / 数据块数</p>
        <p>每台服务器存储 = 总存储需求 / 服务器数量</p>
        
        <p><strong>服务器平均分配:</strong></p>
        <p>每台服务器CPU = 推荐总CPU / 服务器数量</p>
        <p>每台服务器内存 = 推荐总内存 / 服务器数量</p>
        <p>每台服务器虚拟机数 = 总虚拟机数 / 服务器数量</p>
        
        <p><strong>注意事项:</strong></p>
        <p>1. 分布式存储的实际需求取决于副本策略和存储类型</p>
        <p>2. 纠删码存储通常比复制式存储更节省空间，但需要更多计算资源</p>
        <p>3. 实际部署时可能需要考虑服务器硬件规格限制和网络带宽</p>
    </div>

    <script>
        // 初始化页面
        document.addEventListener('DOMContentLoaded', function() {
            // 监听存储类型变化
            document.getElementById('storageType').addEventListener('change', function() {
                const erasureConfig = document.getElementById('erasureConfig');
                if (this.value === 'erasure') {
                    erasureConfig.style.display = 'block';
                } else {
                    erasureConfig.style.display = 'none';
                }
            });
        });

        function toggleAdvancedSettings() {
            const advancedSettings = document.getElementById('advancedSettings');
            const toggleIcon = document.getElementById('toggleIcon');
            
            if (advancedSettings.style.display === 'none' || !advancedSettings.style.display) {
                advancedSettings.style.display = 'block';
                toggleIcon.textContent = '▲';
            } else {
                advancedSettings.style.display = 'none';
                toggleIcon.textContent = '▼';
            }
        }

        function calculateResources() {
            // 获取基本配置
            const vmCount = parseInt(document.getElementById('vmCount').value);
            const cpuPerVM = parseInt(document.getElementById('cpuPerVM').value);
            const ramPerVM = parseFloat(document.getElementById('ramPerVM').value);
            const storagePerVM = parseFloat(document.getElementById('storagePerVM').value);
            
            // 获取超配比
            const cpuOvercommit = parseFloat(document.getElementById('cpuOvercommit').value);
            const ramOvercommit = parseFloat(document.getElementById('ramOvercommit').value);
            const storageOvercommit = parseFloat(document.getElementById('storageOvercommit').value);
            
            // 获取系统预留
            const systemCpuReserve = parseFloat(document.getElementById('systemCpuReserve').value) || 0;
            const systemRamReserve = parseFloat(document.getElementById('systemRamReserve').value) || 0;
            const systemStorageReserve = parseFloat(document.getElementById('systemStorageReserve').value) || 0;
            
            // 获取缓冲百分比
            const cpuBuffer = parseFloat(document.getElementById('cpuBuffer').value) || 0;
            const ramBuffer = parseFloat(document.getElementById('ramBuffer').value) || 0;
            const storageBuffer = parseFloat(document.getElementById('storageBuffer').value) || 0;
            
            // 获取服务器和存储配置
            const serverCount = parseInt(document.getElementById('serverCount').value) || 1;
            const replicaCount = parseInt(document.getElementById('replicaCount').value) || 1;
            const storageType = document.getElementById('storageType').value;
            const dataChunks = parseInt(document.getElementById('dataChunks').value) || 4;
            const parityChunks = parseInt(document.getElementById('parityChunks').value) || 2;
            
            // 计算虚拟机总需求
            const totalVCpu = vmCount * cpuPerVM;
            const totalVRam = vmCount * ramPerVM;
            const totalVStorage = vmCount * storagePerVM;
            
            // 计算物理资源需求（不含缓冲）
            const physicalCpu = Math.ceil(totalVCpu / cpuOvercommit) + systemCpuReserve;
            const physicalRam = Math.ceil(totalVRam / ramOvercommit) + systemRamReserve;
            const physicalStorage = Math.ceil(totalVStorage / storageOvercommit) + systemStorageReserve;
            
            // 计算推荐配置（含缓冲）
            const recommendedCpu = Math.ceil(physicalCpu * (1 + cpuBuffer/100));
            const recommendedRam = Math.ceil(physicalRam * (1 + ramBuffer/100));
            const recommendedStorage = Math.ceil(physicalStorage * (1 + storageBuffer/100));
            
            // 计算分布式存储需求
            let storageTypeText, redundancyFactor, totalStorageWithRedundancy;
            
            if (storageType === 'replicated') {
                storageTypeText = `复制式存储 (${replicaCount}副本)`;
                redundancyFactor = replicaCount;
                totalStorageWithRedundancy = Math.ceil(recommendedStorage * redundancyFactor);
            } else {
                storageTypeText = `纠删码存储 (${dataChunks}+${parityChunks})`;
                redundancyFactor = (dataChunks + parityChunks) / dataChunks;
                totalStorageWithRedundancy = Math.ceil(recommendedStorage * redundancyFactor);
            }
            
            // 计算每台服务器平均分配
            const perServerCpu = Math.ceil(recommendedCpu / serverCount * 10) / 10; // 保留1位小数
            const perServerRam = Math.ceil(recommendedRam / serverCount * 10) / 10;
            const perServerStorage = Math.ceil(totalStorageWithRedundancy / serverCount * 10) / 10;
            const perServerVm = Math.ceil(vmCount / serverCount * 10) / 10;
            
            // 显示结果
            document.getElementById('totalVCpu').textContent = totalVCpu;
            document.getElementById('totalVRam').textContent = totalVRam.toFixed(1);
            document.getElementById('totalVStorage').textContent = totalVStorage.toFixed(1);
            
            document.getElementById('physicalCpu').textContent = physicalCpu;
            document.getElementById('physicalRam').textContent = physicalRam.toFixed(1);
            document.getElementById('physicalStorage').textContent = physicalStorage.toFixed(1);
            
            document.getElementById('recommendedCpu').textContent = recommendedCpu;
            document.getElementById('recommendedRam').textContent = recommendedRam.toFixed(1);
            document.getElementById('recommendedStorage').textContent = recommendedStorage.toFixed(1);
            
            document.getElementById('cpuBufferValue').textContent = cpuBuffer;
            document.getElementById('ramBufferValue').textContent = ramBuffer;
            document.getElementById('storageBufferValue').textContent = storageBuffer;
            
            document.getElementById('storageTypeValue').textContent = storageTypeText;
            document.getElementById('redundancyFactor').textContent = redundancyFactor.toFixed(2);
            document.getElementById('actualPhysicalStorage').textContent = recommendedStorage.toFixed(1);
            document.getElementById('totalStorageWithRedundancy').textContent = totalStorageWithRedundancy.toFixed(1);
            
            document.getElementById('perServerCpu').textContent = perServerCpu.toFixed(1);
            document.getElementById('perServerRam').textContent = perServerRam.toFixed(1);
            document.getElementById('perServerStorage').textContent = perServerStorage.toFixed(1);
            document.getElementById('perServerVm').textContent = perServerVm.toFixed(1);
            
            document.getElementById('result').style.display = 'block';
        }
    </script>
</body>
</html>
